#ifndef TCPCONNECTION_H
#define TCPCONNECTION_H
#include "Buffer.hpp"
#include "EventLoop.hpp"
#include "HttpRequest.hpp"
#include "HttpResponse.hpp"
#include "WebSocketData.hpp"
#include <mutex>
#include <type_traits>

class EventLoop;

class TcpConnection {
public:
    TcpConnection(int& fd, EventLoop* loop)
    :fd_(fd), loop_(loop)
    {
        inputBuffer_ = new Buffer(1024);
        outputBuffer_ = new Buffer(1024);
    };

    inline int getFd(){
        return fd_;
    }

    inline Buffer* getInputBuffer() const {
        return inputBuffer_;
    }

    inline Buffer* getOutputBuffer() const {
        return outputBuffer_;
    }

    inline EventLoop* getLoop() {
        return loop_;
    }

    template<typename T>
    int writeToBuffer(const T& buff){
        std::unique_lock<std::mutex> ulock(outMtx_);
        if (std::is_same<T, std::vector<char>>::value) {
            return outputBuffer_->appendString(buff.data(), buff.size());
        }
        else if (std::is_same<T, std::string>::value) {
            return outputBuffer_->appendString(buff.c_str(), buff.size());
        }
        else {
            return -1;
        }
    }

    int writeSocket();
    int readSocket();    
    void closeConnection();
    ~TcpConnection();

    inline void setHttpRequest(std::shared_ptr<HttpRequest> httpRequest) {
        httpRequest_ = httpRequest;
    }

    inline std::shared_ptr<HttpRequest> getHttpRequest() const {
        return httpRequest_;
    }

    inline void setWSData(std::shared_ptr<WebSocketData> wsData) {
        wsData_ = wsData;
    }

    inline std::shared_ptr<WebSocketData> getWSData(){
        return wsData_;
    }

    inline void upgradToWS(){
        upgradedToWS_ = true;
    }

    inline bool isWebSocket() {
        return upgradedToWS_;
    }




private:
    int fd_;
    Buffer* inputBuffer_;
    Buffer* outputBuffer_;
    std::shared_ptr<HttpRequest> httpRequest_=nullptr;
    std::shared_ptr<WebSocketData> wsData_ = nullptr;
    bool upgradedToWS_=false;
    EventLoop* loop_; // 属于某个eventloop， 用于修改自己的event属性。

    // bool asynIO; // 告诉系统在后续发送时将发送任务提交到线程池（适用于发送任务较大的情况），后续再实现。
    std::mutex inMtx_;
    std::mutex outMtx_;
    
};

#endif